<?php

namespace App\Http\Controllers\Api;

use Ramsey\Uuid\Uuid;
use App\Exceptions\BusinessException;
use App\Http\Resources\UserModelResource;
use App\Models\CustomerModel;
use App\Models\SupplyModel;
use App\Models\UserModel;
use App\Utils\ResponseEnum;
use App\Utils\WeChat\RbhSupplyMiniProgramWechat;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;

class UserController extends ApiController
{
    /**
     * 获取用户列表
     * @param Request $request
     * @return JsonResponse
     */
    public function getList(Request $request): JsonResponse
    {
        $Model = UserModel::where('status', 1);
        if ($request->input('role'))
            $Model = $Model->where('role', 'like', '%' . $request->input('role') . '%');
        if ($request->input('username'))
            $Model = $Model->where('username', 'like', '%' . $request->input('username') . '%');
        if ($request->input('nickname'))
            $Model = $Model->where('nickname', 'like', '%' . $request->input('nickname') . '%');
        return $this->successPaginate($Model->orderByDesc('ID')->paginate($request->input('pageSize', 10)));
    }

    /**
     * 普通账号密码注册
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function register(Request $request): JsonResponse
    {
        $username = $this->verifyString('username');
        $password = $this->verifyString('password');
        $user = UserModel::where('username', $username)->first();
        $customer = CustomerModel::where('Account', $username)->first();
        if ($user || $customer)
            return $this->fail(ResponseEnum::USER_ACCOUNT_REGISTERED);
        $user = $this->saveUser($username, $password, $request->input('nickname') ? $request->input('nickname') : $username);
        $this->syncUserInfo($username, $request->input('mobile') ? $request->input('mobile') : '', $password, $user->uuid);
        return $this->success();
    }

    /**
     * 验证码登录
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function verifyLogin(Request $request): JsonResponse
    {
        $mobile = $this->verifyString('mobile');
        $verify = $this->verifyInteger('verify');
        if (!VerifyController::checkVerifyValid($mobile, $verify))
            return $this->fail(ResponseEnum::USER_SERVICE_VERIFY_INVALID);
        $user = UserModel::where('username', $mobile)->first();
        # 用户存在
        if (!$user) {
            # 查询桌面端数据并同步
            $user = $this->syncCustomerInfo($mobile);
            if (!$user)
                $user = $this->saveUser($mobile, '', $mobile);
        }
        return $this->success(new UserModelResource($user));
    }

    /**
     * 账号密码登录（APP和管理平台）
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function passwordLogin(Request $request): JsonResponse
    {
        $username = $this->verifyString('username');
        $password = $this->verifyString('password');
        $user = UserModel::where('username', $username)->first();
        if (!$user)
            $user = $this->syncCustomerInfo($username);
        if (!$user || $password != $user->password)
            return $this->fail(ResponseEnum::SERVICE_LOGIN_ACCOUNT_ERROR);
        $user->access_token = $user->createToken('user-token')->plainTextToken;
        $user->save();
        return $this->success(new UserModelResource($user));
    }

    /**
     * 微信登录
     * @return JsonResponse
     * @throws BusinessException
     * @throws ClientExceptionInterface
     * @throws DecodingExceptionInterface
     * @throws RedirectionExceptionInterface
     * @throws ServerExceptionInterface
     * @throws TransportExceptionInterface
     */
    public function getUserOpenId(): JsonResponse
    {
        $code = $this->verifyString('code');
        $WeChat = new RbhSupplyMiniProgramWechat();
        $openId = $WeChat->getUserOpenId($code);
        if (!$openId)
            return $this->fail(ResponseEnum::USER_WECHAT_LOGIN_ERROR);
        $user = UserModel::where('openid', $openId)->first();
        return $this->success($user ?: ['openid' => $openId]);
    }

    /**
     * 创建用户
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     * @throws TransportExceptionInterface
     */
    public function saveWeChatUser(Request $request): JsonResponse
    {
        $code = $this->verifyString('code');
        $this->verifyString('openid');
        $WeChat = new RbhSupplyMiniProgramWechat();
        $data = $WeChat->getUserMobile($code);
        if (!$data)
            return $this->fail(ResponseEnum::USER_WECHAT_MOBILE_ERROR);
        $mobile = $data->purePhoneNumber;
        $sid = SupplyModel::where('Mobile', $mobile)->value('ID');
        $user = UserModel::where('mobile', $mobile)->first();
        if ($user)
            $user = $this->updateUserInfo($user, $request, $sid ?: 0);
        else
            $user = $this->saveUser($mobile, '', '', $sid ?: 0);
        return $this->success($user);
    }

    /**
     * 更新用户信息
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function doSave(Request $request): JsonResponse
    {
        $uid = $this->verifyInteger('uid');
        if ($request->has('verify'))
            if (!VerifyController::checkVerifyValid($request->input('mobile'), $request->input('verify')))
                return $this->fail(ResponseEnum::USER_SERVICE_VERIFY_INVALID);
        $user = UserModel::where('id', $uid)->first();
        if (!$user)
            return $this->fail(ResponseEnum::SERVICE_USER_ACCOUNT_ERROR);
        $user = $this->updateUserInfo($user, $request);
        $this->updateCustomerInfo($user->username, $request);
        return $this->success(new UserModelResource($user));
    }

    /**
     * 绑定用户和商家
     * @return JsonResponse
     * @throws BusinessException
     */
    public function bindUserSid(): JsonResponse
    {
        $uid = $this->verifyInteger('uid');
        $sid = $this->verifyInteger('sid');
        UserModel::where('id', $uid)->update(['sid' => $sid]);
        return $this->success(UserModel::where('id', $uid)->first());
    }

    /**
     * 基于openid绑定用户和商家
     * @return JsonResponse
     * @throws BusinessException
     */
    public function bindWechatSupplyByOpenid(): JsonResponse
    {
        $openid = $this->verifyString('openid');
        $sid = $this->verifyInteger('sid');
        $verify = $this->verifyString('verify');
        $mobile = $this->verifyString('mobile');
        if (!VerifyController::checkVerifyValid($mobile, $verify))
            return $this->fail(ResponseEnum::USER_SERVICE_VERIFY_INVALID);
        UserModel::where('openid', $openid)->update(['sid' => $sid]);
        return $this->success([]);
    }

    /**
     * 获取用户信息
     * @param Request $request
     * @return JsonResponse
     */
    public function userInfo(Request $request): JsonResponse
    {
        if ($request->input('uid'))
            $user = UserModel::where('id', $request->input('uid'))->first();
        else
            $user = UserModel::where('access_token', $request->input('access_token'))->first();
        if (!$user)
            return $this->fail(ResponseEnum::CLIENT_DELETED_ERROR);
        return $this->success(new UserModelResource($user));
    }

    /**
     * 设置用户头像
     * @return JsonResponse
     * @throws BusinessException
     */
    public function setUserAvatar(): JsonResponse
    {
        $uid = $this->verifyInteger('uid');
        $avatar = $this->verifyString('avatar');
        $user = UserModel::where('id', $uid)->first();
        if ($user) {
            $user->avatar = $avatar;
            $user->save();
        }
        return $this->success($user);
    }

    /**
     * 退出
     * @return JsonResponse
     */
    public function logout(): JsonResponse
    {
        return $this->success();
    }

    /**
     * 同步桌面端用户数据到主表
     * @param string $username
     * @return mixed
     */
    private function syncCustomerInfo(string $username): mixed
    {
        $customer = CustomerModel::where('Account', $username)->first();
        if (!$customer)
            return null;
        $user = $this->saveUser($username, $customer->PW, $customer->CName);
        $customer->uuid = $user->uuid;
        $customer->save();
        return $user;
    }

    /**
     * 同步用户信息到桌面端数据表
     * @param string $username
     * @param string $mobile
     * @param string $password
     * @param string $uuid
     * @return void
     */
    private function syncUserInfo(string $username, string $mobile, string $password, string $uuid): void
    {
        CustomerModel::create([
            'Account'   => $username,
            'PW'        => $password,
            'CName'     => $username,
            'Mobile'    => $mobile,
            'uuid'      => $uuid
        ]);
    }

    /**
     * 创建用户
     * @param string $username
     * @param string $password
     * @param string $nickname
     * @param int $sid
     * @return mixed
     */
    private function saveUser(string $username, string $password, string $nickname, int $sid = 0): mixed
    {
        return UserModel::create([
            'uuid'          => Uuid::uuid4()->toString(),
            'username'      => $username,
            'password'      => $password,
            'encrypt'       => md5($password),
            'nickname'      => $nickname,
            'mobile'        => is_numeric($username) ? substr(trim($username), 0, 11) : '',
            'status'        => ($password && $nickname) ? 1 : 0,
            'sid'           => $sid,
            'openid'        => request()->input('openid')
        ]);
    }

    /**
     * 更新用户主表信息
     * @param $user
     * @param $request
     * @param int $sid
     * @return mixed
     */
    private function updateUserInfo($user, $request, int $sid = 0): mixed
    {
        if ($request->input('nickname'))
            $user->nickname = $request->input('nickname');
        if ($request->input('password')) {
            $user->password = $request->input('password');
            $user->encrypt = md5($request->input('password'));
        }
        if ($request->input('mobile'))
            $user->mobile = $request->input('mobile');
        if ($request->input('openid'))
            $user->openid = $request->input('openid');
        if ($sid)
            $user->sid = $sid;
        $user->save();
        return $user;
    }

    /**
     * 更新桌面端用户数据信息
     * @param $username
     * @param $request
     * @return void
     */
    private function updateCustomerInfo($username, $request): void
    {
        $data = [];
        if ($request->input('nickname'))
            $data['CName'] = $request->input('nickname');
        if ($request->input('password'))
            $data['PW'] = $request->input('password');
        if ($request->input('mobile'))
            $data['Mobile'] = $request->input('mobile');
        CustomerModel::where('Account', $username)->update($data);
    }

}
